`timescale 1 ns / 1 ns
//////////////////////////////////////////////////////////////////////////////////
// Institute: Peking University 
// Author:    WANG, Pei 
// 
// Date:    21:26:06 11/09/2011 
//////////////////////////////////////////////////////////////////////////////////
module main_test;

reg        clk;
reg        rst;
wire[31:0] dout;


wire[2047:0] in_buff;
wire[2047:0] out_buff;
wire[2047:0] read_row, read_col, write_row;
wire[5:0]    laddr, raddr;
wire[5:0]    write_result_addr;

reg[31:0]  in_array[63:0];
wire[31:0] out_array[63:0], write_array[63:0];

    assign out_array[ 0] = out_buff[  31:   0];
    assign out_array[ 1] = out_buff[  63:  32];
    assign out_array[ 2] = out_buff[  95:  64];
    assign out_array[ 3] = out_buff[ 127:  96];
    assign out_array[ 4] = out_buff[ 159: 128];
    assign out_array[ 5] = out_buff[ 191: 160];
    assign out_array[ 6] = out_buff[ 223: 192];
    assign out_array[ 7] = out_buff[ 255: 224];
    assign out_array[ 8] = out_buff[ 287: 256];
    assign out_array[ 9] = out_buff[ 319: 288];
    assign out_array[10] = out_buff[ 351: 320];
    assign out_array[11] = out_buff[ 383: 352];
    assign out_array[12] = out_buff[ 415: 384];
    assign out_array[13] = out_buff[ 447: 416];
    assign out_array[14] = out_buff[ 479: 448];
    assign out_array[15] = out_buff[ 511: 480];
    assign out_array[16] = out_buff[ 543: 512];
    assign out_array[17] = out_buff[ 575: 544];
    assign out_array[18] = out_buff[ 607: 576];
    assign out_array[19] = out_buff[ 639: 608];
    assign out_array[20] = out_buff[ 671: 640];
    assign out_array[21] = out_buff[ 703: 672];
    assign out_array[22] = out_buff[ 735: 704];
    assign out_array[23] = out_buff[ 767: 736];
    assign out_array[24] = out_buff[ 799: 768];
    assign out_array[25] = out_buff[ 831: 800];
    assign out_array[26] = out_buff[ 863: 832];
    assign out_array[27] = out_buff[ 895: 864];
    assign out_array[28] = out_buff[ 927: 896];
    assign out_array[29] = out_buff[ 959: 928];
    assign out_array[30] = out_buff[ 991: 960];
    assign out_array[31] = out_buff[1023: 992];
    assign out_array[32] = out_buff[1055:1024];
    assign out_array[33] = out_buff[1087:1056];
    assign out_array[34] = out_buff[1119:1088];
    assign out_array[35] = out_buff[1151:1120];
    assign out_array[36] = out_buff[1183:1152];
    assign out_array[37] = out_buff[1215:1184];
    assign out_array[38] = out_buff[1247:1216];
    assign out_array[39] = out_buff[1279:1248];
    assign out_array[40] = out_buff[1311:1280];
    assign out_array[41] = out_buff[1343:1312];
    assign out_array[42] = out_buff[1375:1344];
    assign out_array[43] = out_buff[1407:1376];
    assign out_array[44] = out_buff[1439:1408];
    assign out_array[45] = out_buff[1471:1440];
    assign out_array[46] = out_buff[1503:1472];
    assign out_array[47] = out_buff[1535:1504];
    assign out_array[48] = out_buff[1567:1536];
    assign out_array[49] = out_buff[1599:1568];
    assign out_array[50] = out_buff[1631:1600];
    assign out_array[51] = out_buff[1663:1632];
    assign out_array[52] = out_buff[1695:1664];
    assign out_array[53] = out_buff[1727:1696];
    assign out_array[54] = out_buff[1759:1728];
    assign out_array[55] = out_buff[1791:1760];
    assign out_array[56] = out_buff[1823:1792];
    assign out_array[57] = out_buff[1855:1824];
    assign out_array[58] = out_buff[1887:1856];
    assign out_array[59] = out_buff[1919:1888];
    assign out_array[60] = out_buff[1951:1920];
    assign out_array[61] = out_buff[1983:1952];
    assign out_array[62] = out_buff[2015:1984];
    assign out_array[63] = out_buff[2047:2016];
    
    assign in_buff[  31:   0] = in_array[ 0];
    assign in_buff[  63:  32] = in_array[ 1];
    assign in_buff[  95:  64] = in_array[ 2];
    assign in_buff[ 127:  96] = in_array[ 3];
    assign in_buff[ 159: 128] = in_array[ 4];
    assign in_buff[ 191: 160] = in_array[ 5];
    assign in_buff[ 223: 192] = in_array[ 6];
    assign in_buff[ 255: 224] = in_array[ 7];
    assign in_buff[ 287: 256] = in_array[ 8];
    assign in_buff[ 319: 288] = in_array[ 9];
    assign in_buff[ 351: 320] = in_array[10];
    assign in_buff[ 383: 352] = in_array[11];
    assign in_buff[ 415: 384] = in_array[12];
    assign in_buff[ 447: 416] = in_array[13];
    assign in_buff[ 479: 448] = in_array[14];
    assign in_buff[ 511: 480] = in_array[15];
    assign in_buff[ 543: 512] = in_array[16];
    assign in_buff[ 575: 544] = in_array[17];
    assign in_buff[ 607: 576] = in_array[18];
    assign in_buff[ 639: 608] = in_array[19];
    assign in_buff[ 671: 640] = in_array[20];
    assign in_buff[ 703: 672] = in_array[21];
    assign in_buff[ 735: 704] = in_array[22];
    assign in_buff[ 767: 736] = in_array[23];
    assign in_buff[ 799: 768] = in_array[24];
    assign in_buff[ 831: 800] = in_array[25];
    assign in_buff[ 863: 832] = in_array[26];
    assign in_buff[ 895: 864] = in_array[27];
    assign in_buff[ 927: 896] = in_array[28];
    assign in_buff[ 959: 928] = in_array[29];
    assign in_buff[ 991: 960] = in_array[30];
    assign in_buff[1023: 992] = in_array[31];
    assign in_buff[1055:1024] = in_array[32];
    assign in_buff[1087:1056] = in_array[33];
    assign in_buff[1119:1088] = in_array[34];
    assign in_buff[1151:1120] = in_array[35];
    assign in_buff[1183:1152] = in_array[36];
    assign in_buff[1215:1184] = in_array[37];
    assign in_buff[1247:1216] = in_array[38];
    assign in_buff[1279:1248] = in_array[39];
    assign in_buff[1311:1280] = in_array[40];
    assign in_buff[1343:1312] = in_array[41];
    assign in_buff[1375:1344] = in_array[42];
    assign in_buff[1407:1376] = in_array[43];
    assign in_buff[1439:1408] = in_array[44];
    assign in_buff[1471:1440] = in_array[45];
    assign in_buff[1503:1472] = in_array[46];
    assign in_buff[1535:1504] = in_array[47];
    assign in_buff[1567:1536] = in_array[48];
    assign in_buff[1599:1568] = in_array[49];
    assign in_buff[1631:1600] = in_array[50];
    assign in_buff[1663:1632] = in_array[51];
    assign in_buff[1695:1664] = in_array[52];
    assign in_buff[1727:1696] = in_array[53];
    assign in_buff[1759:1728] = in_array[54];
    assign in_buff[1791:1760] = in_array[55];
    assign in_buff[1823:1792] = in_array[56];
    assign in_buff[1855:1824] = in_array[57];
    assign in_buff[1887:1856] = in_array[58];
    assign in_buff[1919:1888] = in_array[59];
    assign in_buff[1951:1920] = in_array[60];
    assign in_buff[1983:1952] = in_array[61];
    assign in_buff[2015:1984] = in_array[62];
    assign in_buff[2047:2016] = in_array[63];
    
    assign write_array[ 0] = write_row[  31:   0];
    assign write_array[ 1] = write_row[  63:  32];
    assign write_array[ 2] = write_row[  95:  64];
    assign write_array[ 3] = write_row[ 127:  96];
    assign write_array[ 4] = write_row[ 159: 128];
    assign write_array[ 5] = write_row[ 191: 160];
    assign write_array[ 6] = write_row[ 223: 192];
    assign write_array[ 7] = write_row[ 255: 224];
    assign write_array[ 8] = write_row[ 287: 256];
    assign write_array[ 9] = write_row[ 319: 288];
    assign write_array[10] = write_row[ 351: 320];
    assign write_array[11] = write_row[ 383: 352];
    assign write_array[12] = write_row[ 415: 384];
    assign write_array[13] = write_row[ 447: 416];
    assign write_array[14] = write_row[ 479: 448];
    assign write_array[15] = write_row[ 511: 480];
    assign write_array[16] = write_row[ 543: 512];
    assign write_array[17] = write_row[ 575: 544];
    assign write_array[18] = write_row[ 607: 576];
    assign write_array[19] = write_row[ 639: 608];
    assign write_array[20] = write_row[ 671: 640];
    assign write_array[21] = write_row[ 703: 672];
    assign write_array[22] = write_row[ 735: 704];
    assign write_array[23] = write_row[ 767: 736];
    assign write_array[24] = write_row[ 799: 768];
    assign write_array[25] = write_row[ 831: 800];
    assign write_array[26] = write_row[ 863: 832];
    assign write_array[27] = write_row[ 895: 864];
    assign write_array[28] = write_row[ 927: 896];
    assign write_array[29] = write_row[ 959: 928];
    assign write_array[30] = write_row[ 991: 960];
    assign write_array[31] = write_row[1023: 992];
    assign write_array[32] = write_row[1055:1024];
    assign write_array[33] = write_row[1087:1056];
    assign write_array[34] = write_row[1119:1088];
    assign write_array[35] = write_row[1151:1120];
    assign write_array[36] = write_row[1183:1152];
    assign write_array[37] = write_row[1215:1184];
    assign write_array[38] = write_row[1247:1216];
    assign write_array[39] = write_row[1279:1248];
    assign write_array[40] = write_row[1311:1280];
    assign write_array[41] = write_row[1343:1312];
    assign write_array[42] = write_row[1375:1344];
    assign write_array[43] = write_row[1407:1376];
    assign write_array[44] = write_row[1439:1408];
    assign write_array[45] = write_row[1471:1440];
    assign write_array[46] = write_row[1503:1472];
    assign write_array[47] = write_row[1535:1504];
    assign write_array[48] = write_row[1567:1536];
    assign write_array[49] = write_row[1599:1568];
    assign write_array[50] = write_row[1631:1600];
    assign write_array[51] = write_row[1663:1632];
    assign write_array[52] = write_row[1695:1664];
    assign write_array[53] = write_row[1727:1696];
    assign write_array[54] = write_row[1759:1728];
    assign write_array[55] = write_row[1791:1760];
    assign write_array[56] = write_row[1823:1792];
    assign write_array[57] = write_row[1855:1824];
    assign write_array[58] = write_row[1887:1856];
    assign write_array[59] = write_row[1919:1888];
    assign write_array[60] = write_row[1951:1920];
    assign write_array[61] = write_row[1983:1952];
    assign write_array[62] = write_row[2015:1984];
    assign write_array[63] = write_row[2047:2016];


reg[1:0]    imem_wen;
wire         omem_wen;
reg[5:0]    meml_addr, memr_addr, memo_addr;

// memory for the left operand of GEMM
mem_1024X64 mem_l0(.clka(clk), .wea(imem_wen[0]), .addra(meml_addr), .dina(in_buff[1023:0]), .douta(read_row[1023:0]));
mem_1024X64 mem_l1(.clka(clk), .wea(imem_wen[0]), .addra(meml_addr), .dina(in_buff[2047:1024]), .douta(read_row[2047:1024]));

// memory for the right operand of GEMM
mem_1024X64 mem_r0(.clka(clk), .wea(imem_wen[1]), .addra(memr_addr), .dina(in_buff[1023:0]), .douta(read_col[1023:0]));
mem_1024X64 mem_r1(.clka(clk), .wea(imem_wen[1]), .addra(memr_addr), .dina(in_buff[2047:1024]), .douta(read_col[2047:1024]));

// memroy for the result of GEMM
mem_1024X64 mem_o0(.clka(clk), .wea(omem_wen), .addra(memo_addr), .dina(write_row[1023:0]), .douta(out_buff[1023:0]));
mem_1024X64 mem_o1(.clka(clk), .wea(omem_wen), .addra(memo_addr), .dina(write_row[2047:1024]), .douta(out_buff[2047:1024]));

reg[5:0] recv_addr, send_addr;

reg state, ctr_cal_prepare;

initial begin
    in_array[ 0] = 0;
in_array[ 1] = 0;
in_array[ 2] = 0;
in_array[ 3] = 0;
in_array[ 4] = 0;
in_array[ 5] = 0;
in_array[ 6] = 0;
in_array[ 7] = 0;
in_array[ 8] = 0;
in_array[ 9] = 0;
in_array[10] = 0;
in_array[11] = 0;
in_array[12] = 0;
in_array[13] = 0;
in_array[14] = 0;
in_array[15] = 0;
in_array[16] = 0;
in_array[17] = 0;
in_array[18] = 0;
in_array[19] = 0;
in_array[20] = 0;
in_array[21] = 0;
in_array[22] = 0;
in_array[23] = 0;
in_array[24] = 0;
in_array[25] = 0;
in_array[26] = 0;
in_array[27] = 0;
in_array[28] = 0;
in_array[29] = 0;
in_array[30] = 0;
in_array[31] = 0;
in_array[32] = 0;
in_array[33] = 0;
in_array[34] = 0;
in_array[35] = 0;
in_array[36] = 0;
in_array[37] = 0;
in_array[38] = 0;
in_array[39] = 0;
in_array[40] = 0;
in_array[41] = 0;
in_array[42] = 0;
in_array[43] = 0;
in_array[44] = 0;
in_array[45] = 0;
in_array[46] = 0;
in_array[47] = 0;
in_array[48] = 0;
in_array[49] = 0;
in_array[50] = 0;
in_array[51] = 0;
in_array[52] = 0;
in_array[53] = 0;
in_array[54] = 0;
in_array[55] = 0;
in_array[56] = 0;
in_array[57] = 0;
in_array[58] = 0;
in_array[59] = 0;
in_array[60] = 0;
in_array[61] = 0;
in_array[62] = 0;
in_array[63] = 0;    
    clk = 0;
    rst = 1;
    state = 0;
    recv_addr = 0;
    send_addr = 0;
    imem_wen = 0;
    #10;
    rst = 0;
    #10;
    imem_wen[0] = 1;
    in_array[0] = 2;
    in_array[1] = 3;
    recv_addr = 0;
    #10;
    recv_addr = 1;
    in_array[0] = 4;
    in_array[1] = 0;
    #10;
    in_array[0] = 0;
    in_array[1] = 0;
    recv_addr = 2;
    #10;
    recv_addr = 3;
    #10;
    recv_addr = 4;
    #10;
    recv_addr = 5;
    #10;
    recv_addr = 6;
    #10;
    recv_addr = 7;
    #10;
    recv_addr = 8;
    #10;
    recv_addr = 9;
    #10;
    recv_addr = 10;
    #10;
    recv_addr = 11;
    #10;
    recv_addr = 12;
    #10;
    recv_addr = 13;
    #10;
    recv_addr = 14;
    #10;
    recv_addr = 15;
    #10;
    recv_addr = 16;
    #10;
    recv_addr = 17;
    #10;
    recv_addr = 18;
    #10;
    recv_addr = 19;
    #10;
    recv_addr = 20;
    #10;
    recv_addr = 21;
    #10;
    recv_addr = 22;
    #10;
    recv_addr = 23;
    #10;
    recv_addr = 24;
    #10;
    recv_addr = 25;
    #10;
    recv_addr = 26;
    #10;
    recv_addr = 27;
    #10;
    recv_addr = 28;
    #10;
    recv_addr = 29;
    #10;
    recv_addr = 30;
    #10;
    recv_addr = 31;
    #10;
    recv_addr = 32;
    #10;
    recv_addr = 33;
    #10;
    recv_addr = 34;
    #10;
    recv_addr = 35;
    #10;
    recv_addr = 36;
    #10;
    recv_addr = 37;
    #10;
    recv_addr = 38;
    #10;
    recv_addr = 39;
    #10;
    recv_addr = 40;
    #10;
    recv_addr = 41;
    #10;
    recv_addr = 42;
    #10;
    recv_addr = 43;
    #10;
    recv_addr = 44;
    #10;
    recv_addr = 45;
    #10;
    recv_addr = 46;
    #10;
    recv_addr = 47;
    #10;
    recv_addr = 48;
    #10;
    recv_addr = 49;
    #10;
    recv_addr = 50;
    #10;
    recv_addr = 51;
    #10;
    recv_addr = 52;
    #10;
    recv_addr = 53;
    #10;
    recv_addr = 54;
    #10;
    recv_addr = 55;
    #10;
    recv_addr = 56;
    #10;
    recv_addr = 57;
    #10;
    recv_addr = 58;
    #10;
    recv_addr = 59;
    #10;
    recv_addr = 60;
    #10;
    recv_addr = 61;
    #10;
    recv_addr = 62;
    #10;
    recv_addr = 63;
    #10;
    imem_wen = 2'b10;
    in_array[0] = 2;
    in_array[1] = 3;
    recv_addr = 0;
    #10;
    recv_addr = 1;
    in_array[0] = 4;
    in_array[1] = 0;
    #10;
    in_array[0] = 0;
    in_array[1] = 0;
    recv_addr = 2;
    #10;
    recv_addr = 3;
    #10;
    recv_addr = 4;
    #10;
    recv_addr = 5;
    #10;
    recv_addr = 6;
    #10;
    recv_addr = 7;
    #10;
    recv_addr = 8;
    #10;
    recv_addr = 9;
    #10;
    recv_addr = 10;
    #10;
    recv_addr = 11;
    #10;
    recv_addr = 12;
    #10;
    recv_addr = 13;
    #10;
    recv_addr = 14;
    #10;
    recv_addr = 15;
    #10;
    recv_addr = 16;
    #10;
    recv_addr = 17;
    #10;
    recv_addr = 18;
    #10;
    recv_addr = 19;
    #10;
    recv_addr = 20;
    #10;
    recv_addr = 21;
    #10;
    recv_addr = 22;
    #10;
    recv_addr = 23;
    #10;
    recv_addr = 24;
    #10;
    recv_addr = 25;
    #10;
    recv_addr = 26;
    #10;
    recv_addr = 27;
    #10;
    recv_addr = 28;
    #10;
    recv_addr = 29;
    #10;
    recv_addr = 30;
    #10;
    recv_addr = 31;
    #10;
    recv_addr = 32;
    #10;
    recv_addr = 33;
    #10;
    recv_addr = 34;
    #10;
    recv_addr = 35;
    #10;
    recv_addr = 36;
    #10;
    recv_addr = 37;
    #10;
    recv_addr = 38;
    #10;
    recv_addr = 39;
    #10;
    recv_addr = 40;
    #10;
    recv_addr = 41;
    #10;
    recv_addr = 42;
    #10;
    recv_addr = 43;
    #10;
    recv_addr = 44;
    #10;
    recv_addr = 45;
    #10;
    recv_addr = 46;
    #10;
    recv_addr = 47;
    #10;
    recv_addr = 48;
    #10;
    recv_addr = 49;
    #10;
    recv_addr = 50;
    #10;
    recv_addr = 51;
    #10;
    recv_addr = 52;
    #10;
    recv_addr = 53;
    #10;
    recv_addr = 54;
    #10;
    recv_addr = 55;
    #10;
    recv_addr = 56;
    #10;
    recv_addr = 57;
    #10;
    recv_addr = 58;
    #10;
    recv_addr = 59;
    #10;
    recv_addr = 60;
    #10;
    recv_addr = 61;
    #10;
    recv_addr = 62;
    #10;
    recv_addr = 63;
    #10;
    imem_wen = 0;
    recv_addr = 0;
    #10;
    recv_addr = 1;
    #10;
    state = 1;
    ctr_cal_prepare = 1;
    #10;
    ctr_cal_prepare = 0;
    #40970;
    state = 0;
    send_addr = 0;
    #10;
    send_addr = 1;
end;

always begin
    #5;
    clk = ~clk;
end;

// control meml_addr
always @(*) begin
    if(state == 1)
        meml_addr = laddr;
    else
        meml_addr = recv_addr;
end

// control memr_addr
always @(*) begin
    if(state == 1)
        memr_addr = raddr;
    else
        memr_addr = recv_addr;
end

// control memo_addr
always @(*) begin
    if(state == 1)
        memo_addr = write_result_addr;
    else
        memo_addr = send_addr;
end

// calculation unit    
matrix_mul multiplier(
    .din_row(read_row),
    .din_col(read_col),
    .clk(clk),
    .rst(ctr_cal_prepare),
    .busy(state_cal),
    .cwen(omem_wen),
    .iaddr_row(laddr),
    .iaddr_col(raddr),
    .oaddr(write_result_addr),
    .dout(write_row)
    );

endmodule
